jae syscall_badsys
call *sys_call_table(,%eax,4)
movl %eax,EAX(%esp)
- cli
+ DISABLE_INTERRUPTS
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx
jne syscall_exit_work
movl EIP(%esp), %edx
movl OLDESP(%esp), %ecx
xorl %ebp,%ebp
+#ifdef CONFIG_XEN
+ __ENABLE_INTERRUPTS
+sysexit_scrit: /**** START OF SYSEXIT CRITICAL REGION ****/
+ __TEST_PENDING
+ jnz 14f # process more events if necessary...
+ movl ESI(%esp), %esi
+ sysexit
+14: __DISABLE_INTERRUPTS
+sysexit_ecrit: /**** END OF SYSEXIT CRITICAL REGION ****/
+ push %esp
+ call evtchn_do_upcall
+ add $4,%esp
+ jmp ret_from_intr
+#else
sti
sysexit
+#endif /* !CONFIG_XEN */
# system call handler stub
# So, on entry to the handler we detect whether we interrupted an
# existing activation in its critical region -- if so, we pop the current
# activation and restart the handler using the previous one.
+#
+# The sysexit critical region is slightly different. sysexit
+# atomically removes the entire stack frame. If we interrupt in the
+# critical region we know that the entire frame is present and correct
+# so we can simply throw away the new one.
ENTRY(hypervisor_callback)
pushl %eax
SAVE_ALL
jb 11f
cmpl $ecrit,%eax
jb critical_region_fixup
+ cmpl $sysexit_scrit,%eax
+ jb 11f
+ cmpl $sysexit_ecrit,%eax
+ ja 11f
+ addl $0x34,%esp # Remove cs...ebx from stack frame.
11: push %esp
call evtchn_do_upcall
add $4,%esp
#include <asm/pgtable.h>
#include <asm/unistd.h>
+#ifdef CONFIG_XEN
+#include <xen/interface/callback.h>
+#endif
+
extern asmlinkage void sysenter_entry(void);
void enable_sep_cpu(void)
{
syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+#ifdef CONFIG_XEN
+ if (boot_cpu_has(X86_FEATURE_SEP)) {
+ struct callback_register sysenter = {
+ .type = CALLBACKTYPE_sysenter,
+ .address = { __KERNEL_CS, (unsigned long)sysenter_entry },
+ };
+
+ if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0)
+ clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability);
+ }
+#endif
+
if (boot_cpu_has(X86_FEATURE_SEP)) {
memcpy(syscall_page,
&vsyscall_sysenter_start,